/**
 * Copyright (c) 2012-2014 All Rights Reserved.
 */
package com.easy.framwork.jdbc;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.easy.framwork.exceptions.JdbcException;
import com.easy.framwork.jdbc.handlers.ListBeanHandler;
import com.easy.framwork.jdbc.handlers.ListColumnNameMapHandler;
import com.easy.framwork.jdbc.handlers.ResultSetHandler;
import com.easy.framwork.jdbc.handlers.SingleBeanHandler;
import com.easy.framwork.jdbc.handlers.SingleColumnNameMapHandler;
import com.easy.framwork.jdbc.query.Delete;
import com.easy.framwork.jdbc.query.Insert;
import com.easy.framwork.jdbc.query.Select;
import com.easy.framwork.jdbc.query.Update;

/**
 * 
 * @author wy
 * @version v 0.1 2014-1-3 上午10:44:48 wy Exp $
 */
public class Jdbc {

    protected final Logger log = LoggerFactory.getLogger(getClass());

    protected final Connection conn;

    /**
     * 
     * @param conn
     */
    public Jdbc(Connection conn) {
        this.conn = conn;
    }

    /**
     * query for map
     * 
     * @param sql
     * @param params
     * @return
     */
    public Map<String, Object> queryForMap(String sql, Object... params) {
        QueryHelper queryHelper = new QueryHelper();
        try {
            return queryHelper.query(conn, sql, new SingleColumnNameMapHandler(), params);
        }
        catch (SQLException e) {
            log.error("query for object error", e);
            throw new JdbcException("query for object error");
        }
    }

    /**
     * query for map
     * 
     * @param sql
     * @param params
     * @return
     */
    public List<Map<String, Object>> queryForListMap(String sql, Object... params) {
        QueryHelper queryHelper = new QueryHelper();
        try {
            return queryHelper.query(conn, sql, new ListColumnNameMapHandler(), params);
        }
        catch (SQLException e) {
            log.error("query for object error", e);
            throw new JdbcException("query for object error");
        }
    }

    /**
     * query for map
     * 
     * @param select
     * @return
     */
    public Map<String, Object> queryForMap(Select select) {
        return this.queryForMap(select.getSQL(), select.getParams());
    }

    /**
     * query for map
     * 
     * @param select
     * @return
     */
    public List<Map<String, Object>> queryForListMap(Select select) {
        return this.queryForListMap(select.getSQL(), select.getParams());
    }

    /**
     * query for object
     * 
     * @param clazz
     * @param sql
     * @param params
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T queryForObject(Class<T> clazz, String sql, Object... params) {
        if (Map.class.isAssignableFrom(clazz)) {
            return (T) queryForMap(sql, params);
        }
        return this.query(sql, new SingleBeanHandler<T>(clazz), params);
    }

    /**
     * query for object
     * 
     * @param clazz
     * @param select
     * @return
     */
    public <T> T queryForObject(Class<T> clazz, Select select) {
        return this.queryForObject(clazz, select.getSQL(), select.getParams());
    }

    /**
     * query for list
     * 
     * @param clazz
     * @param sql
     * @param params
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> List<T> queryForList(Class<T> clazz, String sql, Object... params) {
        if (Map.class.isAssignableFrom(clazz)) {
            return (List<T>) queryForListMap(sql, params);
        }
        return this.query(sql, new ListBeanHandler<T>(clazz), params);
    }

    /**
     * query for list
     * 
     * @param clazz
     * @param select
     * @return
     */
    public <T> List<T> queryForList(Class<T> clazz, Select select) {
        return this.queryForList(clazz, select.getSQL(), select.getParams());
    }

    /**
     * query for String
     * 
     * @param sql
     * @param params
     * @return
     */
    public String queryForString(String sql, Object... params) {
        return this.queryForObject(String.class, sql, params);
    }

    /**
     * query for String
     * 
     * @param select
     * @return
     */
    public String queryForyString(Select select) {
        return this.queryForString(select.getSQL(), select.getParams());
    }

    /**
     * query for integer
     * 
     * @param sql
     * @param params
     * @return
     */
    public Integer queryForInt(String sql, Object... params) {
        return this.queryForObject(Integer.class, sql, params);
    }

    /**
     * query for integer
     * 
     * @param select
     * @return
     */
    public Integer queryForInt(Select select) {
        return this.queryForInt(select.getSQL(), select.getParams());
    }

    /**
     * query for Long
     * 
     * @param sql
     * @param params
     * @return
     */
    public Long queryForLong(String sql, Object... params) {
        return this.queryForObject(Long.class, sql, params);
    }

    /**
     * query for select
     * 
     * @param sql
     * @return
     */
    public Long queryForLong(Select select) {
        return this.queryForLong(select.getSQL(), select.getParams());
    }

    /**
     * query
     * 
     * @param sql
     * @param rsh
     * @param params
     * @return
     */
    public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) {
        QueryHelper queryHelper = new QueryHelper();
        try {
            return queryHelper.query(conn, sql, rsh, params);
        }
        catch (SQLException e) {
            log.error("query for list error", e);
            throw new JdbcException("query for list error");
        }
    }

    /**
     * query
     * 
     * @param select
     * @param rsh
     * @return
     */
    public <T> T query(Select select, ResultSetHandler<T> rsh) {
        return query(select.getSQL(), rsh, select.getParams());
    }

    /**
     * update
     * 
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public int update(String sql, Object... params) {
        QueryHelper queryHelper = new QueryHelper();
        try {
            return queryHelper.update(conn, sql, params);
        }
        catch (SQLException e) {
            log.error("update error", e);
            throw new JdbcException("update error");
        }
    }

    /**
     * update
     * 
     * @param update
     * @return
     */
    public int update(Update update) {
        return this.update(update.getSQL(), update.getParams());
    }

    /**
     * insert
     * 
     * @param insert
     * @return
     */
    public int insert(Insert insert) {
        return this.update(insert.getSQL(), insert.getParams());
    }

    /**
     * delete
     * 
     * @param delete
     * @return
     */
    public int delete(Delete delete) {
        return this.update(delete.getSQL(), delete.getParams());
    }

    /**
     * get Connection
     * 
     * @return conn
     */
    public Connection getConnection() {
        return conn;
    }

}
